<?php

namespace app\common\shopify;

use app\admin\model\OrderItem;
use app\admin\service\ProductInventory;
use app\api\model\LogisticsOrderItem;
use app\common\RedisClient;
use app\common\service\Inventory;
use Mpdf\Tag\Dd;
use PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\DateTime;
use think\facade\Config;
use think\facade\Db;
use think\facade\Log;
use think\Exception;

class OrderService extends BaseClient
{
    protected $maxRetries = 3;
    protected $retryCount = 0;
    protected $orderUpdateRedisKey = "shopify_last_order_update";
    protected $orderRedisKey = "shopify_last_order_id";

    public function syncOrders(int $limit = 250)
    {
        $lastOrderId = $this->getLastSyncedOrderId();
        $lastUpdate = $this->getLastSyncedOrderUp();
        $cursor = null;
        $maxOrderId = $lastOrderId;
        $startTime = microtime(true);
        $orderCount = 0;
        $itemCount = 0;
        $updateTime = $lastUpdate;
        $ordersToUpdate = []; // +++ 新增：需更新的订单 +++
//        do {
            $this->retryCount = 0;
            $orders = $this->getOrdersWithRetry($limit, $cursor, $updateTime,$lastOrderId);
            Log::info(" [shopify] 处理订单数量: " . count($orders['edges']));
            if (empty($orders['edges'])){
                Log::info(" [shopify] 本次无数据需要处理" );
                return;
            }

            $batchData = [];
            $batchOrderExsce = [];//数据问题跳过订单
            $batchItems = [];
            $batchCustomers = [];
            $batchRelations = [];
            $fulfillmentMappings = [];
            $shopifyCustomerIds = [];
            $ordersToUpdate = [];
            foreach ($orders['edges'] as $edge) {
                $shopifyOrder = $edge['node'];
                if (!empty($shopifyOrder['customer'])) {
                    $customer = $shopifyOrder['customer'];
                    $shopifyCustomerId = $customer['id'];
                    $shopifyCustomerIds[$shopifyCustomerId] = $customer;
                }
            }

            $customerIdMap = $this->processCustomers($shopifyCustomerIds);
            Log::info(" [shopify] 处理客户数量: " . count($shopifyCustomerIds) . " → 匹配客户ID映射数量: " . count($customerIdMap));

            // +++ 修改点：区分新增/更新订单逻辑 +++
            foreach ($orders['edges'] as $edge) {
                $shopifyOrder = $edge['node'];
                $orderNo = $shopifyOrder['name'];
                $localOrder = Db::name('order')->where('order_no', $orderNo)->where('is_del',0)->find();
                Log::info(" [shopify] 订单信息： {$orderNo }  ：".json_encode($localOrder));
                $fulfillmentStatus = $shopifyOrder['displayFulfillmentStatus'] ?? 'UNFULFILLED'; // 获取履行状态
                $displayFinancialStatus = $shopifyOrder['displayFinancialStatus'] ?? 'PAID'; // 获取履行状态
                $maxOrderId =  $shopifyOrder['legacyResourceId'];
                $updateTime = $shopifyOrder['updatedAt'];
                // +++ 新增：收集履约项映射 +++
                $fulfillmentMappings[$orderNo] = [];
                if (!empty($shopifyOrder['fulfillment_line_item_mapping'])) {
                    Log::info(" [shopify] 订单{$orderNo}开始处理履约映射，行项目数量: " . count($shopifyOrder['fulfillment_line_item_mapping']));
                    foreach ($shopifyOrder['fulfillment_line_item_mapping'] as $lineItemId => $mapping) {
                        $fulfillmentIds = array_column($mapping, 'fulfillment_order_line_item_id');
                        $fulfillmentMappings[$orderNo][$lineItemId] = $fulfillmentIds;
                        Log::info(" [shopify] └── 行项目{$lineItemId} → 履约ID: " . implode(',', $fulfillmentIds));
                    }
                } else {
                    Log::info(" [shopify] 订单{$orderNo}无履约映射数据");
                }
                // +++ 核心修改：根据履行状态分流 +++
                if (!$localOrder) {
                    $localCustomerId = null;
                    $shopifyCustomerId = $shopifyOrder['customer']['id'] ?? null;
                    if ($shopifyCustomerId) {
                        $localCustomerId = $customerIdMap[$shopifyCustomerId] ?? null;
                    }

                    $mappedOrder = $this->mapOrderFields($shopifyOrder, $localCustomerId);
                    Log::info(" [shopify] 订单号： {$orderNo } 发货状态： {$fulfillmentStatus}  ， 订单支付状态： {$displayFinancialStatus}");

                    // 未履行 → 新增订单
                    $batchData[] = $mappedOrder;

                    // 保存关联关系（需要订单ID）
                    if ($localCustomerId) { // +++ 等待订单ID生成 +++
                        $batchRelations[] = [
                            'order_id' => null, // 占位符，插入后更新
                            'order_no_temp' => $orderNo,
                            'customer_id' => $localCustomerId,
                            'shopify_order_id' => $shopifyOrder['legacyResourceId'],
                            'shopify_customer_id' => $shopifyCustomerId,
                            'create_time' => date('Y-m-d H:i:s')
                        ];
                    }


                    // 处理商品（含库存锁定）
                    foreach ($shopifyOrder['lineItems']['edges'] as $itemEdge) {
                        $itemData = $this->mapOrderItemFields(
                            $itemEdge['node'],
                            $orderNo,
                            $shopifyCustomerId
                        );
                        if ($itemData) {
                            $batchItems[] = $itemData;
                            $itemCount++;
                        }else{
                            Log::info(" [shopify] 订单{$orderNo} 订单行数据 不正确");
                            $batchOrderExsce[] =  $orderNo;
                        }

                    }
                    $orderCount++;
                }
//                 其他状态 → 标记为需更新
                $ordersToUpdate[$orderNo] = [
                    'shopify_data' => $shopifyOrder,
                    'fulfillment_status' => $fulfillmentStatus,
                    'fulfillment_map' => $fulfillmentMappings[$orderNo],
                    'pay_status' => $displayFinancialStatus
                ];

            }

            // 批量保存新增订单
            if (!empty($batchData)) {
                Log::info(" [shopify] 准备保存批量订单，数量: " . count($batchData));
                $this->saveBatchOrders($batchData, $batchItems, $batchRelations, $customerIdMap, $fulfillmentMappings,$batchOrderExsce);
            }

            // +++ 新增：处理订单更新 +++
            if (!empty($ordersToUpdate)) {
                $this->updateOrders($ordersToUpdate);
            }

//            $cursor = $orders['pageInfo']['hasNextPage'] ? end($orders['edges'])['cursor'] : null;
//        } while ($cursor);

        $this->updateLastSyncedOrderId($maxOrderId);
        $this->updateLastSyncedOrderUp($updateTime);
        $duration = round(microtime(true) - $startTime, 2);
        Log::info(" [shopify] 同步完成! 新增订单:{$orderCount} 更新订单:" . count($ordersToUpdate) . " 用时:{$duration}秒");
    }

    /**
     * +++ 新增方法：更新订单状态 +++
     */
    private function updateOrders(array $ordersToUpdate)
    {
        foreach ($ordersToUpdate as $orderNo => $orderData) {
            $shopifyOrder = $orderData['shopify_data'];
            $sku_quantities = $shopifyOrder['sku_quantities'];
            $pay_status = $orderData['pay_status'];
            $fulfillment_map = $orderData['fulfillment_map'];


                // 1. 获取本地订单
                $localOrder = Db::name('order')->where('order_no', $orderNo)->where('is_del',0)->find();
                if (!$localOrder) {
                    Log::info(" [shopify] 订单{$orderNo}不存在，跳过更新");
                    continue;
                }
                // 2. 根据状态执行操作
            switch ($pay_status) {
                case 'REFUNDED':
                    // 取消订单 同步订单状态
                    if ($localOrder['status'] != 70) {
                        #取消订单 释放库存
                        try {
                            $this->unlockInventory($localOrder);
                        } catch (\Exception $e) {
                            Log::info(" [shopify] 订单{$orderNo}库存释放失败");

                        }
                        Db::name('order')->where('id', $localOrder['id'])->update([
                            'status' => 70, // 标记为已支付
                        ]);
                    }
                    Db::name('order')->where('id', $localOrder['id'])->update([
                        'total_amount' => 0,
                        'pay_amount' => 0,
                        'logistics_fee' => 0,
                        'product_total_amount' => 0,
                        'product_total_original_amount' => 0,
                        'order_num' => 0,
                        'first_leg_logistics_fee' => 0,
                        'update_time' => date('Y-m-d H:i:s')

                    ]);
                    Log::info(" [shopify] 订单{$orderNo}状态更新: 原状态：{$localOrder['status']}→已取消");
                    break;

                    case 'PARTIALLY_REFUNDED':
                    case 'PARTIALLY_PAID':
                    case 'PAID':
                        #处理订单行
                        Db::startTrans();
                        try {
                            $pending_quantity = $this->processUpdateOrder($localOrder, $shopifyOrder,$fulfillment_map);
                            $refund = $shopifyOrder['refund_mapping'];
                            $total_refund_num = 0;
                            $total_num = 0;
                            foreach ($sku_quantities as $iterm_num) {
                                $total_num += $iterm_num;
                            }
                            if ($refund['relation']) {
                                foreach ($refund['relation'] as $sku => $num) {
                                    $total_refund_num += $num;
                                }
                            }

                            $totalPrice = $shopifyOrder['currentTotalPriceSet']['presentmentMoney']['amount'] ?? '0.00';
                            $currentSubtotalPriceSet = $shopifyOrder['currentSubtotalPriceSet']['presentmentMoney']['amount'] ?? '0.00';
                            $totalReceivedSet = $shopifyOrder['totalReceivedSet']['presentmentMoney']['amount'] ?? '0.00';
                            $orderInfo = \app\api\model\Order::where('id', $localOrder['id'])->where('is_del', 0)->find();
                            $orderInfo->product_total_amount = $currentSubtotalPriceSet;
                            $orderInfo->product_total_original_amount = $currentSubtotalPriceSet;
                            $orderInfo->total_amount = $totalPrice;
                            $orderInfo->pay_amount = max(0.00, $totalReceivedSet - $refund['refund_fee']);
                            Log::info('  [shopify]  待发数量：' .$pending_quantity . ' 订单总数量： '.($total_num - $total_refund_num));
                            if ($orderInfo->pay_amount > 0) {
                                if ($orderInfo->total_amount > $orderInfo->pay_amount) {
                                    $orderInfo->status = 10;
                                    $orderInfo->pay_status = 4;
                                } else {
                                    $orderInfo->status = 30;
                                    if($pending_quantity == 0){
                                        $orderInfo->status = 50;
                                    }elseif ( $pending_quantity != ($total_num - $total_refund_num)){
                                        $orderInfo->status = 40;
                                    }
                                    $orderInfo->pay_status = 3;
                                }

                            } else {
                                $orderInfo->status = 10;
                                $orderInfo->pay_status = 1;
                            }
                            $orderInfo->order_num = $total_num - $total_refund_num;
                            $orderInfo->logistics_fee = $shopifyOrder['totalShippingPrice'];
                            $orderInfo->save();

                            Db::commit();
                    } catch (\Exception $e) {
                        Db::rollback();
                        Log::info('  [shopify]  订单更新失败：' . $e->getMessage());
                    }

                    break;
                    // 可扩展其他状态...
                }
        }
    }
    private function processUpdateOrder($localOrder, $shopifyOrder,$fulfillment_map)
    {

        $shippedQtys = $this->getShippedQtys($localOrder['id']);
        Log::info('  [shopify]  发货信息：' . json_encode($shippedQtys));
        // +++ 新增：获取行项目映射关系 +++
        $relation = Db::name('order_shopify_relation')
            ->where('order_id', $localOrder['id'])
            ->find();

        $itemMapping = json_decode($relation['itemdetail'] ?? '{}', true)['line_item_mapping'] ?? [];
        $allItemsValid = true; // 标记所有商品行是否有效
        $item_ids = [];
        $lock_param = [];
        $pending_quantity = 0;
        $local_item_ids = Db::name('order_item')->where('order_id',$localOrder['id'])->column('id');

        Log::info('  [shopify]  订单行对应关系：' . json_encode($itemMapping));
        $order_item_ids = array_values($itemMapping);
       if(count($local_item_ids) != count($order_item_ids)){
           Log::error("  [shopify]  订单:{$localOrder['id']}有过调仓等操作，此订单不进行更新");
           throw new Exception("订单有过调仓等操作，此订单不进行更新");
       }
            foreach ($shopifyOrder['lineItems']['edges'] as $itemEdge) {
                $node = $itemEdge['node'];
                $lineItemId = $node['id'];
                $fulfillment_line_item_mapping = $shopifyOrder['fulfillment_line_item_mapping'][$lineItemId];
                Log::info("  [shopify]  订单行发货 ： $lineItemId :" . json_encode(array_column($fulfillment_line_item_mapping,'remaining_quantity')));
                $line_pending_quantity = array_sum(array_column($fulfillment_line_item_mapping,'remaining_quantity'));
                $refundQty = $shopifyOrder['refund_mapping']['relation'][$lineItemId] ?? 0;
                $newQty = max(0, $node['quantity'] - $refundQty);
                Log::info('  [shopify]  订单行商品新数量：' . $newQty);
                if (isset($itemMapping[$lineItemId])) {
                    if($newQty <= 0 ){
                        continue;
                    }
                    $shippedQty = 0;
                    $itermInfo = Db::name('order_item')->where('id', $itemMapping[$lineItemId])->where('is_del',0)->find();
                    Log::info('  [shopify]  本地订单行：' . json_encode($itermInfo));
                    if($itermInfo['product_id'] != 0 &&  $itermInfo['warehouse_id'] != 0){

                        // +++ 商品数量校验 +++ [8](@ref)
                        $key = $itermInfo['product_id'] . '_' . $itermInfo['warehouse_id'];
                        $shippedQty = $shippedQtys[$key] ?? 0;
                        if ($newQty< $shippedQty) {
                            throw new Exception("商品数量不能小于已发货量($shippedQty)");
                        }
                        #释放库存
                        if($localOrder['review_node'] != 1 && $itermInfo['pending_quantity'] >0){
                            $unlock_param = [[
                                'order_id' => $localOrder['id'],
                                'product_id' => $itermInfo['product_id'],
                                'arrival_date' => $itermInfo['arrival_date'],
                                'is_futures' => $itermInfo['is_futures'],
                                'wid' => $itermInfo['warehouse_id'],
                                'quantity' => $itermInfo['pending_quantity'],
                            ]];
                            $unlock = (new Inventory())->unlockInventory($unlock_param);
                            if(!$unlock){
                                throw new Exception("释放库存失败 订单不更新");
                            }
                            Log::info('  [shopify]  释放库存：' . $unlock);
                        }

                    }
                    Log::info('  [shopify]  已发数量：' . json_encode($shippedQty));
                    $shippedQty = $itermInfo['quantity'] - $itermInfo['pending_quantity'];
                    Log::info('  [shopify]  订单行已发货数量：' . json_encode($shippedQty));
                    $for_update = $newQty - $shippedQty;
                    Db::name('order_item')->where('id', $itemMapping[$lineItemId])->update(['quantity'=>$newQty,
                        'pending_quantity'=> $for_update]);
                    $pending_quantity += $for_update;
                    if($for_update >0){
                        #锁定库存
                        $lock_param[] =[
                            'order_id' => $localOrder['id'],
                            'product_id' => $itermInfo['product_id'],
                            'arrival_date' => $itermInfo['arrival_date'],
                            'is_futures' => $itermInfo['is_futures'],
                            'warehouse_id' => $itermInfo['warehouse_id'],
                            'quantity' => $for_update,
                        ];
                    }
                    $item_ids[] = $itemMapping[$lineItemId];

                }else{
                    $newItemData = $this->mapOrderItemFields($node, $localOrder['order_no'],$relation['customer_id']);
                    unset($newItemData['order_no_temp']);
                    unset($newItemData['shopify_iterm_id']);
                    $newItemData['order_id'] = $localOrder['id'];
                    $newItemId = Db::name('order_item')->insertGetId($newItemData);
                    $item_ids[] = $newItemId;
                    #锁定库存
                    $lock_param[] = [
                        'order_id' => $localOrder['id'],
                        'product_id' => $newItemData['product_id'],
                        'arrival_date' => $newItemData['arrival_date'],
                        'is_futures' => $newItemData['is_futures'],
                        'warehouse_id' => $newItemData['warehouse_id'],
                        'quantity' => $newItemData['quantity'],
                    ];
                    $pending_quantity += $newItemData['quantity'];
                    $relation = Db::name('order_shopify_relation')
                        ->where('order_id', $localOrder['id'])
                        ->find();
                    $itemMap = json_decode($relation['itemdetail'] ?? '{}', true);
                    Log::info('  [shopify]  订单行关系：' . $newQty);
                    // 更新映射关系
                    $itemMap['line_item_mapping'][$lineItemId] = $newItemId;
                    $itemMap['iterm_relation'][] = [
                        'local_order_item_id' =>$newItemId,
                        'fulfillment_ids'=>$fulfillment_map[$lineItemId] ?? []
                    ];
                    Db::name('order_shopify_relation')
                        ->where('order_id', $localOrder['id'])
                        ->update([
                            'itemdetail' => json_encode($itemMap)
                        ]);
                }

            }
            if($lock_param){
                $lock = (new Inventory())->lockInventoryByItem($lock_param);
                Log::info('  [shopify]  锁定库存结果：' . $lock);
                if(!$lock){
                    $this->updateAllOrderAfterLockInventoryFail($localOrder['id']);
                }
            }

            Log::info(' [shopify] 已修改订单行ids ：' . json_encode($item_ids));
            /* 去除已删掉的 item */
            $DelOrderItem = OrderItem::where('order_id', $localOrder['id'])->where('is_del', 0);
            if (count($item_ids) > 0) {
                $DelOrderItem =  $DelOrderItem->whereNotIn('id', $item_ids);
            }
            $toDelete = $DelOrderItem->select();
            Log::info('  [shopify]  待删除订单行详情：' . json_encode($toDelete->toArray()));
            Log::info(' [shopify]  已发货信息：' . json_encode($shippedQtys));
            // +++ 删除前检查已发货量 +++ [8](@ref)
            foreach ($toDelete as $item) {
                #释放库存
                if($localOrder['review_node'] != 1 && $item['pending_quantity'] > 0){
                    $unlock_param = [[
                        'order_id' => $localOrder['id'],
                        'product_id' => $item['product_id'],
                        'arrival_date' => $item['arrival_date'],
                        'is_futures' => $item['is_futures'],
                        'wid' => $item['warehouse_id'],
                        'quantity' => $item['pending_quantity'],
                    ]];
                    $unlock = (new Inventory())->unlockInventory($unlock_param);
                    Log::info('  [shopify]  释放库存：' . $unlock);
                    if(!$unlock){
                        throw new Exception("释放库存失败 订单不更新");
                    }
                }
            }
            if (count($item_ids) > 0) {
                $DelOrderItem->whereNotIn('id', $item_ids)->update(['is_del' => time()]);
            } else {
                $DelOrderItem->update(['is_del' => time()]);
            }
            return $pending_quantity;
    }
    #库存锁定失败 更新订单 和订单行状态
    public function updateOrderAfterLockInventoryFail($id,$item_id)
    {
        #锁定失败 标记异常
        $orderInfo = \app\api\model\Order::where('id', $id)->where('is_del', 0)->find();
        if ($orderInfo) {
            $orderInfo->review_node = 1;
            $orderInfo->exceptionstatus = 1;
            $orderInfo->save();
            \app\api\model\OrderItem::where('id', $item_id)->update(['exceptionstatus' => 1]);
        }
    }
    private function unlockInventory($localOrder)
    {
        if ($localOrder['review_node'] != 1) {
            try {
                $items = \app\api\model\OrderItem::where('order_id', $localOrder['id'])->where('is_del',0)->select()->toArray();
                if (empty($items)) {
                    throw new \Exception('订单商品不存在');
                }
                $condition = [];
                foreach ($items as $item) {
                    $condition[] = [
                        'order_id' => $localOrder['id'],
                        'productid' => $item['product_id'],
                        'wid' => $item['warehouse_id'],
                        'arrival_date' => $item['arrival_date'],
                        'is_futures' => $item['is_futures'],
                        'quantity' => $item['pending_quantity']
                    ];
                }
               $result =  ( new Inventory())->unlockInventory($condition);
                return $result;
            } catch (\Exception $e) {
                Log::error(" [shopify] 单条 释放库存失败: {$e->getMessage()}");
                return false;
            }
        }
        return true;
    }
// +++ 新增：获取已发货数量方法 +++ [3](@ref)
    private function getShippedQtys($orderId)
    {
        $shippedData = Db::name('logistics_order_item')
            ->alias('loi')
            ->join('logistics_order lo', 'loi.logistics_order_id = lo.id')
            ->where('loi.order_id', $orderId)
            ->where('lo.type', 1)
            ->field('product_id, number as shipped_qty,warehouse_id')
            ->select();

        $result = [];

        foreach ($shippedData as $item) {
            $key = $item['product_id'] . '_' . $item['warehouse_id'];
            if (!isset($result[$key])) {
                $result[$key] = 0;
            }
            $result[$key] += $item['shipped_qty'];
        }

        return $result;
    }
    /**
     * 修改GraphQL查询：加入客户字段
     */
    private function fetchOrders(int $limit, ?string $cursor,$up, $sinceId): array
    {
        // 获取上次处理订单的创建时间
        $time = Config::get('shopify.time');
        $condition = "(financial_status:paid OR financial_status:partially_paid OR  financial_status:partially_refunded OR financial_status:refunded) AND created_at:>'{$time}'";
        if ($up) {
            $condition = $condition . " AND updated_at:>'{$up}'";
        }


        $query = <<<'GRAPHQL'
query GetOrders($first: Int!, $after: String, $query: String) {
    orders(
        first: $first
        after: $after
        query: $query
        sortKey: UPDATED_AT
    ) {
        edges {
            cursor
            node {
                id
                legacyResourceId
                name
                email
                createdAt
                updatedAt
                totalPrice
                totalShippingPrice
                totalWeight
                note
                displayFinancialStatus
                displayFulfillmentStatus
                currentTotalPriceSet {
                    presentmentMoney {
                        amount
                        currencyCode
                    }
                }
                currentSubtotalPriceSet {
                    presentmentMoney {
                        amount
                        currencyCode
                    }
                }
                totalReceivedSet {
                    presentmentMoney {
                        amount
                        currencyCode
                    }
                }
                shippingAddress {
                    firstName
                    lastName
                    address1
                    address2
                    city
                    country
                    zip
                    province
                    phone
                    company
                }
                customer {
                    id
                    firstName
                    lastName
                    email
                    phone
                }
                lineItems(first: 20) {
                    edges {
                        node {
                            id
                            title
                            quantity
                            variant {
                                id
                                sku
                            }
                            originalUnitPriceSet {
                                presentmentMoney {
                                    amount
                                    currencyCode
                                }
                            }
                            discountedUnitPriceSet {
                                presentmentMoney {
                                    amount
                                    currencyCode
                                }
                            }
                        }
                    }
                }
                fulfillmentOrders(first: 10) {
                    edges {
                        node {
                            id
                            status
                            lineItems(first: 20) {
                                edges {
                                    node {
                                        id
                                        lineItem {
                                            id
                                        }
                                        totalQuantity
                                        remainingQuantity
                                    }
                                }
                            }
                        }
                    }
                }
                refunds(first: 10) {
                    id
                    createdAt
                    note
                    totalRefundedSet {
                        presentmentMoney {
                            amount
                            currencyCode
                        }
                    }
                    refundLineItems(first: 20) {
                        nodes {
                            id
                            quantity
                            priceSet {
                                presentmentMoney {
                                    amount
                                    currencyCode
                                }
                            }
                            lineItem {
                                id
                                name
                                title
                                sku
                                variant {
                                    id
                                    title
                                }
                            }
                        }
                    }
                    transactions(first: 10) {
                        edges {
                            node {
                                id
                                kind
                                status
                                amountSet {
                                    presentmentMoney {
                                        amount
                                        currencyCode
                                    }
                                }
                                gateway
                                processedAt
                            }
                        }
                    }
                }
            }
        }
        pageInfo {
            hasNextPage
            endCursor
        }
    }
}
GRAPHQL;
        $variables = [
            'first' => $limit,
            'after' => $cursor,
            'query' => $condition,
        ];

        $response = $this->graphqlRequest($query, $variables);
        if (!empty($response['errors'])) {
            $this->processGraphQLErrors($response['errors']);
        }

        $orders = $response['orders'] ?? [];
//        #删除第一个重复的元素
        $orderUpdate = $orders['edges'][0]['node']['updatedAt'] ?? '';
        $orderUpdateId = $orders['edges'][0]['node']['legacyResourceId'] ?? '';
        if($orderUpdate && $orderUpdateId && $orderUpdate == $up && $orderUpdateId == $sinceId){
            $orders['edges'] = array_values(array_slice( $orders['edges'], 1, null, true));
        }
        // 在代码中过滤掉已处理的订单
        if (!empty($orders['edges'])) {

            $orders['edges'] = $this->processFulfillmentOrderLineItemMapping($orders['edges']);
        }
        Log::info(" [shopify] 获取订单数据: " . count($orders['edges'] ?? []) . "条");
        Log::info(" [shopify] 获取订单数据: " .json_encode($orders));
        return $orders;
    }

    /**
     * 处理FulfillmentOrderLineItem与LineItem的对应关系
     *
     * @param array $orderEdges
     * @return array
     */
    private function processFulfillmentOrderLineItemMapping(array $orderEdges): array
    {
        Log::info(" [shopify] 开始处理履约项映射，订单数量: " . count($orderEdges));
        foreach ($orderEdges as &$orderEdge) {
            $order = &$orderEdge['node'];
            $orderName = $order['name'] ?? '未知订单';

            // 建立LineItem ID到FulfillmentOrderLineItem ID的映射
            $fulfillmentLineItemMapping = [];

            if (!empty($order['fulfillmentOrders']['edges'])) {
                Log::info(" [shopify] 订单{$orderName}开始处理履约项");
                foreach ($order['fulfillmentOrders']['edges'] as $fulfillmentOrderEdge) {
                    $fulfillmentOrder = $fulfillmentOrderEdge['node'];
                    $fulfillmentOrderId = $fulfillmentOrder['id'] ?? '';

                    if (!empty($fulfillmentOrder['lineItems']['edges'])) {
                        Log::info(" [shopify] ├── 履约单{$fulfillmentOrderId}包含行项目数量: " . count($fulfillmentOrder['lineItems']['edges']));
                        foreach ($fulfillmentOrder['lineItems']['edges'] as $fulfillmentLineItemEdge) {
                            $fulfillmentLineItem = $fulfillmentLineItemEdge['node'];
                            $lineItemId = $fulfillmentLineItem['lineItem']['id'];
                            $fulfillmentLineItemId = $fulfillmentLineItem['id'];

                            Log::info(" [shopify] │   行项目{$lineItemId} → 履约项{$fulfillmentLineItemId}");

                            // 建立映射关系
                            if (!isset($fulfillmentLineItemMapping[$lineItemId])) {
                                $fulfillmentLineItemMapping[$lineItemId] = [];
                            }

                            $fulfillmentLineItemMapping[$lineItemId][] = [
                                'fulfillment_order_line_item_id' => $fulfillmentLineItemId,
                                'fulfillment_order_id' => $fulfillmentOrder['id'],
                                'total_quantity' => $fulfillmentLineItem['totalQuantity'],
                                'remaining_quantity' => $fulfillmentLineItem['remainingQuantity'],
                                'status' => $fulfillmentOrder['status']
                            ];
                        }
                    } else {
                        Log::info(" [shopify] ├── 履约单{$fulfillmentOrderId}无行项目");
                    }
                }
            } else {
                Log::info(" [shopify] 订单{$orderName}无履约单数据");
            }

            // --- 2. 新增：SKU下单数量统计 ---
            $skuQuantities = []; // 初始化SKU数量映射表
            if (!empty($order['lineItems']['edges'])) {
                foreach ($order['lineItems']['edges'] as $lineItemEdge) {
                    $lineItem = $lineItemEdge['node'];
                    $sku = $this->resolveSku($lineItem); // 统一SKU解析
                    $quantity = $lineItem['quantity'];

                    // 累加SKU数量（优化点：避免多次isset检查）
                    $skuQuantities[$sku] = ($skuQuantities[$sku] ?? 0) + $quantity;
                }
            }
            $refundedSkus = [
                'refund_fee' => 0,
                'relation' => [],
            ];
            // 检查订单是否有退款记录
            if (!empty($order['refunds'])) {

                // 遍历所有退款记录
                foreach ($order['refunds'] as $refund) {
                    // 检查退款是否有商品行项目
                    if (empty($refund['refundLineItems']['nodes'])) {
                        continue;
                    }
                    $refundedSkus['refund_fee'] += $refund['totalRefundedSet']['presentmentMoney']['amount'];
                    // 遍历退款的商品行项目
                    foreach ($refund['refundLineItems']['nodes'] as $refundLineItem) {
                        $lineItem = $refundLineItem['lineItem'];
                        $refundQuantity = $refundLineItem['quantity'];
                        if (isset($refundedSkus['relation'][$lineItem['id']])) {
                            $refundedSkus['relation'][$lineItem['id']] += $refundQuantity;
                        } else {
                            $refundedSkus['relation'][$lineItem['id']] = $refundQuantity;
                        }
                        // 获取SKU，优先从variant获取，如果没有则从lineItem获取
                        $sku = null;
                        if (!empty($lineItem['variant']['id']) && !empty($lineItem['sku'])) {
                            $sku = $lineItem['sku'];
                        } elseif (!empty($lineItem['variant']['title']) && $lineItem['variant']['title'] !== 'Default Title') {
                            // 如果没有SKU但有变体标题，可以使用变体标题作为标识
                            $sku = $lineItem['title'] . ' - ' . $lineItem['variant']['title'];
                        } else {
                            // 如果都没有，使用商品标题
                            $sku = $lineItem['title'];
                        }

                        // 累加同一SKU的退款数量
                        if (isset($refundedSkus['relation'][$sku])) {
                            $refundedSkus['relation'][$sku] += $refundQuantity;
                        } else {
                            $refundedSkus['relation'][$sku] = $refundQuantity;
                        }
                    }
                }
            }

            // 将映射关系添加到订单数据中
            $order['fulfillment_line_item_mapping'] = $fulfillmentLineItemMapping;
            $order['refund_mapping'] = $refundedSkus;
            $order['sku_quantities'] = $skuQuantities; // 新增字段：SKU下单数量
            Log::info(" [shopify] 订单{$orderName}处理完成，建立映射数量: " . count($fulfillmentLineItemMapping));
        }

        Log::info(" [shopify] 履约项映射处理完成");
        return $orderEdges;
    }

    /**
     * 新增：SKU解析方法（性能优化）
     */
    private function resolveSku(array $lineItem): string
    {
        // 优先从变体获取SKU（避免冗余判断）
        if (!empty($lineItem['variant']['sku'])) {
            return $lineItem['variant']['sku'];
        }

        // 次选方案：标题组合（优化字符串拼接）
        $title = $lineItem['title'] ?? '无标题商品';
        $variantTitle = $lineItem['variant']['title'] ?? '';

        // 处理默认变体标题（减少冗余输出）
        return ($variantTitle && $variantTitle !== 'Default Title')
            ? "{$title} - {$variantTitle}"
            : $title;
    }
    // ==== 修改方法：批量保存（增加关系表） ====
    // +++ 新增参数 $fulfillmentMappings +++
// ==== 修改方法：批量保存（增加关系表） ====
// +++ 新增参数 $fulfillmentMappings +++
    private function saveBatchOrders(array $orders, array $items, array $relations = [], $customerIdMap = [],
                                     array $fulfillmentMappings = [],$batchOrderExsce=[])
    {
        Db::startTrans();
        try {
            Log::info(" [shopify] 开始批量保存订单，数量: " . count($orders));
            Log::info(" [shopify] 已经存在订单号:  ".json_encode($batchOrderExsce));
            // 1. +++ 修复：批量插入订单并获取订单ID数组 +++
            $orderIds = [];
            $orderMap = [];

            foreach ($orders as $order) {
                if(!$order['user_id']){
                    Log::info(" [shopify] 客户不存在 不需要保存订单: {$order['order_no']} ");
                    continue;
                }
                #订单行数据有问题 跳过订单
                if(in_array($order['order_no'],$batchOrderExsce)){
                    Log::info(" [shopify] 订单已经存在: {$order['order_no']} ");
                    continue;
                }
                #如果存在订单，会更新支付状态
                $orderInfoLocal = \app\api\model\Order::where('order_no', $order['order_no'])->find();
                if ($orderInfoLocal) {
                    if ($orderInfoLocal->pay_status != $order['pay_status']) {
                        $orderInfoLocal->pay_status = $order['pay_status'];
                        $orderInfoLocal->save();
                    }
                    continue;
                }
                $orderId = \app\api\model\Order::insertGetId($order); // 逐条插入获取ID
                if ($orderId) {
                    $orderIds[] = ['id'=>$orderId,'status'=>$order['status']];
                    $orderMap[$order['order_no']] = $orderId;
                    Log::info(" [shopify] 保存订单: {$order['order_no']} → ID:{$orderId}");
                }
            }
            // 2. +++ 修复：构建订单号→订单ID映射（避免array_combine类型错误）+++
            Log::info(" [shopify] 订单ID映射建立: " . count($orderMap) . "条");

            // 3. 处理订单商品关联
            $itemMap = []; // +++ 新增：商品ID映射 +++
            $lineItemMap = []; // 格式: [订单号][lineItem_id] = order_item_id
            Log::info(" [shopify] 开始处理商品项，数量: " . count($items));

            foreach ($items as $i => &$item) {
                if (isset($orderMap[$item['order_no_temp']])) {
                    $item['order_id'] = $orderMap[$item['order_no_temp']];
                    $item['user_id'] = $customerIdMap[$item['user_id']] ?? 0;
                    $insert_iterm = $item;
                    unset($insert_iterm['order_no_temp']);
                    unset($insert_iterm['shopify_iterm_id']);
                    #判断是否有库存
                    if($item['warehouse_id'] == 0){
                        \app\api\model\Order::where('id',$item['order_id'])->update(['review_node'=>1,'exceptionstatus'=>3]);
                    }

                    // 保存订单项并获取ID
                    $itemId = \app\api\model\OrderItem::insertGetId($insert_iterm);

                    if ($itemId) {
                        $itemMap[$i] = $itemId;
                        Log::info(" [shopify] 保存商品项: {$item['shopify_iterm_id']} → ID:{$itemId}");
                        $lineItemMap[$item['order_no_temp']][ $item['shopify_iterm_id']] = $itemId; // 本地order_item_id
                    }
                }
            }

            // +++ 新增：处理并保存履约关系 +++
            if (!empty($fulfillmentMappings)) {
                Log::info(" [shopify] 开始处理履约映射，涉及订单数量: " . count($fulfillmentMappings));
                $relationUpdates = [];
                foreach ($relations as &$rel) {
                    $orderNo = $rel['order_no_temp'] ?? '';
                    Log::info(" [shopify] 开始处理订单{$orderNo}的履约关系");

                    if (isset($orderMap[$orderNo]) && !empty($fulfillmentMappings[$orderNo])) {
                        $mappedData = [];
                        $mappingCount = 0;

                        Log::info(" [shopify] 订单{$orderNo}存在履约映射数据，数量: " . count($fulfillmentMappings[$orderNo]));
                        if (isset($lineItemMap[$orderNo])) {
                            $mappedData['line_item_mapping'] = $lineItemMap[$orderNo];
                        }
                        foreach ($items as $i => $item) {
                            if (($item['order_no_temp'] ?? '') === $orderNo && isset($itemMap[$i])) {
                                $lineItemId = $item['shopify_iterm_id'] ?? null; // Shopify行项目ID
                                $localItemId = $itemMap[$i]; // 本地订单项ID
                                Log::info(" [shopify] ├── 处理商品项: 行项目ID={$lineItemId}, 本地项ID={$localItemId}");

                                if ($lineItemId && isset($fulfillmentMappings[$orderNo][$lineItemId])) {
                                    $fulfillmentIds = $fulfillmentMappings[$orderNo][$lineItemId];
                                    Log::info(" [shopify] │   └── 找到履约映射: 行项目{$lineItemId} → 履约ID: " . implode(',', $fulfillmentIds));

                                    $mappedData['iterm_relation'][] = [
                                        'local_order_item_id' => $localItemId,
                                        'fulfillment_ids' => $fulfillmentIds
                                    ];
                                    $mappingCount++;
                                } else {
                                    Log::info(" [shopify] │   └── 未找到行项目{$lineItemId}的履约映射");
                                }
                            }
                        }

                        $rel['itemdetail'] = !empty($mappedData) ? json_encode($mappedData) : null;
                        Log::info(" [shopify] 订单{$orderNo}建立履约映射{$mappingCount}条");
                    } else {
                        $msg = isset($orderMap[$orderNo]) ? "无履约数据" : "未找到订单映射";
                        Log::info(" [shopify] 订单{$orderNo}无法处理履约: {$msg}");
                    }
                }
            } else {
                Log::info(" [shopify] 本批次无履约映射需处理");
            }

            // 5. +++ 修复关系表：补充订单ID +++
            if (!empty($relations)) {
                Log::info(" [shopify] 准备保存订单关系数据，数量: " . count($relations));
                foreach ($relations as $k=>&$rel) {
                    if (isset($rel['order_no_temp']) && isset($orderMap[$rel['order_no_temp']])) {
                        $rel['order_id'] = $orderMap[$rel['order_no_temp']];
                        Log::info(" [shopify] 更新关系表: 订单号{$rel['order_no_temp']} → ID:{$rel['order_id']}");
                        unset($rel['order_no_temp']);
                    }else{
                        unset($relations[$k]);
                    }
                    #gid://shopify/Customer/8476904030301   处理格式
                    if ($rel['shopify_customer_id']) {
                        $shopify_customer_id = explode('/', $rel['shopify_customer_id']);
                        $rel['shopify_customer_id'] = end($shopify_customer_id);
                    }
                }

                Db::name('order_shopify_relation')->insertAll($relations);
                Log::info(" [shopify] 订单关系保存完成");
            }
            #锁定库存
            if ($orderIds) {
                Log::info(" [shopify] 开始锁定库存，订单数量: " . count($orderIds));
                foreach ($orderIds as $order) {
                    if($order['status'] == 30 || $order['status'] == 10){
                        $orderInfoa = \app\api\model\Order::where('id',$order['id'])->find();
                        if($orderInfoa->review_node != 1){
                            $res = (new Inventory())->lockInventory(['id' => $order['id']]);
                            Log::info(" [shopify] 锁定库存结果{$res}  订单id ：{$order['id']}");
                            if(!$res){
                                $this->updateAllOrderAfterLockInventoryFail($order['id']);
                            }
                        }
                    }else{
                        Log::info(" [shopify] 订单状态不对 无需锁定库存 {$order['status']}  订单id ：{$order['id']}");
                    }

                }
            }

            Db::commit();
            Log::info(" [shopify] 批量保存成功: " . count($orders) . "个订单, " . count($items) . "个商品");
        } catch (\Exception $e) {
            Db::rollback();
            Log::error("批量保存失败: {$e->getMessage()}");
            throw new Exception("数据库批量操作失败: {$e->getMessage()}");
        }
    }
    #库存锁定失败 更新订单 和订单行状态
    private function updateAllOrderAfterLockInventoryFail($id)
    {
        #锁定失败 标记异常
        $orderInfo = \app\api\model\Order::where('id',$id)->where('is_del',0)->find();
        if($orderInfo){
            $orderInfo->review_node = 1;
            $orderInfo->exceptionstatus = 1;
            $orderInfo->save();
            \app\api\model\OrderItem::where('order_id', $id)->update(['exceptionstatus'=>1]);
        }
    }
    // ==== 修改方法：订单字段映射 ====
    private function mapOrderFields(array $shopifyOrder, ?int $customerId = null): array
    {
        $createdAt = date('Y-m-d H:i:s', strtotime($shopifyOrder['createdAt']));
        $updatedAt = date('Y-m-d H:i:s', strtotime($shopifyOrder['updatedAt']));
        $address = $shopifyOrder['shippingAddress'] ?? [];
        $order_num = 0;
        foreach ($shopifyOrder['lineItems']['edges'] as $itemEdge) {
            $order_num +=$itemEdge['node']['quantity'];
        }
        $country = $address['country'] ?? null;
        $city = $address['city'] ?? null;
        $province = $address['province'] ?? null;
        $status = 30;
        if( $shopifyOrder['displayFulfillmentStatus'] == 'FULFILLED'){
            $status = 50;
        }elseif ($shopifyOrder['displayFulfillmentStatus'] == 'PARTIALLY_FULFILLED')
        {
            $status = 40;
        }
        $ret = [
            'order_no' => $shopifyOrder['name'],
            'user_id' => $customerId,
            'order_type' => 1,
            'delivery_method' => 1,
            'email' => $shopifyOrder['email'],
            'create_time' => $createdAt,
            'update_time' => $updatedAt,
            'country_name' => $country,
            'city_name' => $city,
            'zip_code' => $address['zip'] ?? null,
            'state' => $province,
            'company' => $address['company'] ?? null,
            'phone' => $address['phone'] ?? null,
            'order_num' => $order_num,
            'address' => implode(',',[($address['address1'] ?? ''),($address['address2'] ?? ''),$city,$province,$country]) ,
            'first_name' => $address['firstName'] ?? null,
            'last_name' => $address['lastName'] ?? null,
            'pay_time' => $createdAt,
            'total_amount' => $shopifyOrder['totalPrice'],
            'pay_amount' => $shopifyOrder['totalReceivedSet']['presentmentMoney']['amount'] ?? null,
            'status' => $status,
            'order_weight' => $shopifyOrder['totalWeight'],
            'logistics_fee' => $shopifyOrder['totalShippingPrice'],
            'source' => 2, // +++ 标记为Shopify订单  +++
            'notes' => $shopifyOrder['note'] ?? null,
            'product_total_amount' => $shopifyOrder['currentSubtotalPriceSet']['presentmentMoney']['amount'] ?? null,
            'product_total_original_amount' => $shopifyOrder['currentSubtotalPriceSet']['presentmentMoney']['amount'] ?? null,
        ];
        if(in_array($shopifyOrder['displayFinancialStatus'],['PAID','PARTIALLY_PAID'])){
            $ret['pay_status'] = $shopifyOrder['displayFinancialStatus'] == 'PAID' ? 3 : 4;
            if($shopifyOrder['displayFinancialStatus'] == 'PARTIALLY_PAID'){
                $ret['status'] = 10;
            }
        }else{
            $ret['pay_status'] = $ret['pay_amount'] == $ret['total_amount'] ? 3 : 4;
        }
        return $ret;
    }

    private function mapOrderItemFields(array $shopifyItem, string $orderNo, $shopifyCustomerId): array
    {
        $sku = $shopifyItem['variant']['sku'] ?? '';
        $info = $this->getLocalProductId($sku);
        $wid =$info['wid'] ?? 0;
        return [
            'order_no_temp' => $orderNo,
            'shopify_iterm_id' => $shopifyItem['id'],
            'product_abbr' => substr($shopifyItem['title'],0,255),
            'product_id' => $info['productid'] ?? 0,
            'arrival_date' => $info['arrival_date'] ?? null,
            'real_arrival_date' => $info['real_arrival_date'] ?? null,
            'warehouse_id' => $wid,
            'is_futures' => $info['is_futures'] ?? 0,
            'original_price' => $shopifyItem['originalUnitPriceSet']['presentmentMoney']['amount'],
            'actual_price' => $shopifyItem['discountedUnitPriceSet']['presentmentMoney']['amount'],
            'price_selected_currency' => $shopifyItem['discountedUnitPriceSet']['presentmentMoney']['amount'],
            'quantity' => $shopifyItem['quantity'],
            'pending_quantity' => $shopifyItem['quantity'],
            'user_id' => $shopifyCustomerId,
            'create_time' => date('Y-m-d H:i:s'),
            'exceptionstatus' => $wid == 0 ? 3:null,
        ];
    }

    // ==== 新增方法：客户处理逻辑 ====
    private function processCustomers(array $shopifyCustomers): array
    {
        $idMap = [];
        Log::info(" [shopify] 开始处理客户匹配，数量: " . count($shopifyCustomers));
        foreach ($shopifyCustomers as $shopifyId => $data) {
            $customerId = '';
            $email = $data['email'] ?? '';
            $phone = $data['phone'] ?? '';
            if(!$phone && !$email){
                continue;
            }
            // 1. 优先按邮箱匹配
            if($email){
                $customerId = Db::name('customer')
                    ->where('email', trim($email))
                    ->value('id');
            }

            // 2. 按手机号匹配
            if (!$customerId && $phone) {
                $customerId = Db::name('customer')
                    ->where('phone', trim($phone))
                    ->value('id');
                Log::info(" [shopify] 匹配客户: {$phone} → ID:{$customerId}");
            }

            // 3. 新建客户
            if (!$customerId) {
                $customerId = Db::name('customer')->insertGetId([
                    'email' => $email,
                    'cusname' => explode('@', $email)[0] ?? '',
                    'nickname' => explode('@', $email)[0] ?? '',
                    'phone' => $phone,
                    'first_name' => $data['firstName'] ?? '',
                    'last_name' => $data['lastName'] ?? '',
                    'create_time' => date('Y-m-d H:i:s')
                ]);
                Log::info(" [shopify] 新建客户: {$email} → ID:{$customerId}");
            } else {
                Log::info(" [shopify] 匹配客户: {$email} → ID:{$customerId}");
            }

            $idMap[$shopifyId] = $customerId;
        }
        return $idMap;
    }


    private function getOrdersWithRetry(int $limit, ?string $cursor,$up, $sinceId): array
    {
        $attempt = 0;
        do {
            try {
                return $this->fetchOrders($limit, $cursor,$up, $sinceId);
            } catch (\Exception $e) {
                $attempt++;
                Log::info(" [shopify] 第{$attempt}次重试: {$e->getMessage()}");

                // 指数退避
                $waitTime = pow(2, min($attempt, 6)); // 最大等待64秒
                sleep($waitTime);

                // 最后一次重试仍失败则抛出异常
                if ($attempt >= $this->maxRetries) {
                    throw new Exception("重试{$this->maxRetries}次失败: {$e->getMessage()}");
                }
            }
        } while (true);
    }

    private function processGraphQLErrors(array $errors): void
    {
        foreach ($errors as $error) {
            $message = $error['message'] ?? '未知错误';
            $code = $error['extensions']['code'] ?? 'unknown';

            // 变量未使用错误 - 关键修复点
            if ($code === 'variableNotUsed') {
                $varName = $error['extensions']['variableName'] ?? 'unknown';
                throw new Exception("变量'{$varName}'声明但未使用，请检查查询语句");
            } // 语法错误
            elseif ($code === 'syntaxError') {
                $location = $error['locations'][0] ?? [];
                $line = $location['line'] ?? '?';
                $column = $location['column'] ?? '?';
                throw new Exception("语法错误[行:{$line},列:{$column}]: {$message}");
            } // 限流错误
            elseif ($code === 'throttled') {
                $cost = $error['extensions']['cost'] ?? 0;
                $maxCost = $error['extensions']['maximumAvailable'] ?? 0;
                throw new Exception("API限流 - 当前费用:{$cost} 最大可用:{$maxCost}");
            } // 其他错误
            else {
                Log::error("GraphQL错误: [{$code}] {$message}");
                throw new Exception("API请求失败: {$code}");
            }
        }
    }

    private function getLastSyncedOrderId()
    {
        $redis = new RedisClient();
        $key = $this->orderRedisKey;
        $id = $redis->get($key);
        return $id ?: '';
    }
    private function getLastSyncedOrderUp()
    {
        $redis = new RedisClient();
        $key = $this->orderUpdateRedisKey;
        $id = $redis->get($key);
        return $id ?: '';
    }

    private function updateLastSyncedOrderId($lastId)
    {
        $redis = new RedisClient();
        $key = $this->orderRedisKey;
        $redis->set($key, $lastId);
    }
    private function updateLastSyncedOrderUp($lastId)
    {
        $redis = new RedisClient();
        $key = $this->orderUpdateRedisKey;
        $redis->set($key, $lastId);
    }

    private function getLocalProductId(string $sku)
    {
        if (empty($sku)) {
            return [];
        }

        // ✅ 修改点1：用 strpos 定位首个横杠位置
        $delimiterPos = strpos($sku, '-');
        if ($delimiterPos === false) {
            $skuPrefix = $sku;
            $batchNumber = '';
        }else{
            // ✅ 修改点2：提取横杠前后的子串
            $skuPrefix = substr($sku, 0, $delimiterPos); // 横杠前的SKU
            $batchNumber = substr($sku, $delimiterPos + 1); // 横杠后的完整物流批次
        }

        $productId = Db::name('product')->where('sku', $skuPrefix)->value('id');
        if (!$productId) {
            return [];
        }
        if(!$batchNumber){
            return ['productid'=>$productId];
        }
        $inventory = Db::name('inventory')->where([
            ['productid', '=', $productId],
            ['inbound_batch', '=', $batchNumber], // ✅ 使用完整物流批次
            ['is_del', '=', 0]
        ])->order('create_time asc')->find();
        $inventory['productid'] = $productId;

        return $inventory;
    }

    /**
     * 私有方法：调用Shopify取消订单API（带重试机制）
     */
    public function cancelShopifyOrderApi(string $shopifyOrderId): bool
    {
        Log::info('[shopify] cancle order start  ');
        $graphqlId = 'gid://shopify/Order/' . ltrim($shopifyOrderId, '#');
        $query = <<<'GRAPHQL'
    mutation CancelOrder($orderId: ID!, $refund: Boolean!, $restock: Boolean!, $reason: OrderCancelReason!) {
        orderCancel(
            orderId: $orderId
            refund: $refund
            restock: $restock
            reason: $reason
        ) {
            job { id done }
            orderCancelUserErrors { field message }
        }
    }
GRAPHQL;

        $variables = [
            'orderId' => $graphqlId,
            'refund' => true,
            'restock' => true,
            'reason' => 'INVENTORY'
        ];

        $response = $this->graphqlRequest($query, $variables);
        Log::info('[shopify] cancle response : ' . json_encode($response));
        // 检查API返回错误
        if (!empty($response['errors'])) {
            $this->processGraphQLErrors($response['errors']);
            return false;
        }

        // 检查业务错误
        $userErrors = $response['data']['orderCancel']['userErrors'] ?? [];
        if (empty($userErrors)) {
            return true; // 取消成功
        }
        return false;
    }
}